<template>
  <div class="one-page-container" ref="container">
    <!-- 搜索栏 -->
    <van-search
      v-model="queryParams.deviceAddress"
      placeholder="请输入设备地点"
      show-action
      @search="searchQuery"
    >
      <template #action>
        <div @click="searchQuery">搜索</div>
      </template>
    </van-search>

    <!-- 卡片列表 -->
    <div class="card-list">
      <van-empty v-if="tableData.length === 0" description="暂无数据"/>
      <van-grid :column-num="1" :gutter="10" v-else>
        <van-grid-item v-for="(item, index) in sortedTableData" :key="index">
          <div class="air-card" @click="showDeviceDetail(item)">
            <div class="card-header">
              <div class="device-status">
                <span class="status-dot" :class="item.isOnLine ? 'online' : 'offline'"></span>
                <span class="status-text">{{ item.isOnLine ? '在线' : '离线' }}</span>
              </div>
              <van-icon name="arrow" class="arrow-icon"/>
            </div>

            <div class="card-body">
              <div class="device-info">
                <div class="device-name" :title="item.deviceName">
                  {{ item.deviceName }}
                </div>
                <div class="device-location">
                  <van-icon name="location-o" size="14"/>
                  {{ item.deviceAddress || '未知地点' }}
                </div>
              </div>

              <div class="device-control" v-if="item.isOnLine">
                <div class="temp-control" v-if="isDevicePowerOn(item.uploadData)">
                  <!-- 优化后的模式开关 -->
                  <div class="mode-switch" @click.stop="handleTemCtrl(item, 'temp')">
                    <div class="switch-icon">
                      <img :src="item.uploadData.mode === 3 ? '/hot.png' : '/cool.png'" alt="模式" class="mode-img">
                    </div>
                    <span class="mode-text">
                      {{ item.uploadData.mode === 3 ? '制热' : '制冷' }}
                    </span>
                  </div>
                  <div class="temp-stepper" @click.stop>
                    <van-stepper
                      v-model="item.uploadData.temp"
                      min="17"
                      max="30"
                      integer
                      @change="handleTemCtrl(item, 'tempValue')"
                      :disabled="!isDevicePowerOn(item.uploadData) || loading"
                      disable-input
                    />
                    <span class="temp-unit">℃</span>
                  </div>
                </div>

                <div class="power-control">
                  <!-- 优化后的电源开关 -->
                  <div class="power-switch" @click.stop="changeSwitch(item)">
                    <div class="switch-icon" :class="{'active': isDevicePowerOn(item.uploadData)}">
                      <img :src="isDevicePowerOn(item.uploadData) ? '/open.png' : '/close.png'" alt="电源"
                           class="power-img">
                    </div>
                    <span class="power-text">
                      {{ isDevicePowerOn(item.uploadData) ? '已开启' : '已关闭' }}
                    </span>
                  </div>
                </div>
              </div>
              <div class="offline-mask" v-else>
                设备离线
              </div>
            </div>
          </div>
        </van-grid-item>
      </van-grid>
    </div>

    <!-- 设备详情对话框 -->
    <van-dialog
      v-model="detailDialogVisible"
      title="设备控制"
      :show-cancel-button="false"
      confirm-button-text="关闭"
      :before-close="beforeDialogClose"
    >
      <div class="dialog-content" v-if="currentDevice">
        <div class="control-section" v-if="currentDevice.isOnLine">
          <van-cell-group>
            <van-cell title="电源开关">
              <div class="switch-container">
                <div class="power-switch" @click="togglePower(!isDevicePowerOn(currentDevice.uploadData))">
                  <div class="switch-icon" :class="{'active': isDevicePowerOn(currentDevice.uploadData)}">
                    <img :src="isDevicePowerOn(currentDevice.uploadData) ? '/open.png' : '/close.png'" alt="电源"
                         class="power-img">
                  </div>
                  <span class="power-text">
                    {{ isDevicePowerOn(currentDevice.uploadData) ? '已开启' : '已关闭' }}
                  </span>
                </div>
              </div>
            </van-cell>

            <van-cell title="温度设置" v-if="isDevicePowerOn(currentDevice.uploadData)">
              <van-stepper
                v-model="currentDevice.uploadData.temp"
                min="16"
                max="30"
                disable-input
                integer
                @change="adjustTemperature"
                :disabled="!isDevicePowerOn(currentDevice.uploadData) || loading"
              />
              <span class="temp-unit">℃</span>
            </van-cell>

            <van-cell title="模式选择" v-if="isDevicePowerOn(currentDevice.uploadData)">
              <div class="switch-container">
                <div class="mode-switch" @click="handleTemCtrl(currentDevice, 'temp')">
                  <div class="switch-icon">
                    <img :src="currentDevice.uploadData.mode === 3 ? '/hot.png' : '/cool.png'" alt="模式"
                         class="mode-img">
                  </div>
                  <span class="mode-text">
                    {{ currentDevice.uploadData.mode === 3 ? '制热' : '制冷' }}
                  </span>
                </div>
              </div>
            </van-cell>

            <van-cell title="风速调节" v-if="isDevicePowerOn(currentDevice.uploadData)">
              <div class="wind-control">
                <div class="wind-selector" @click="adjustWindSpeed((currentDevice.uploadData.wind + 1) % 5)">
                  <span class="wind-text">{{ windSpeedMap[currentDevice.uploadData.wind] }}</span>
                  <van-icon name="replay" class="wind-icon"/>
                </div>
              </div>
            </van-cell>
          </van-cell-group>
        </div>

        <div class="detail-section">
          <div class="detail-title">设备详情</div>
          <van-cell-group>
            <van-cell title="在线状态">
              <span :class="currentDevice.isOnLine ? 'text-success' : 'text-danger'">
                {{ currentDevice.isOnLine ? '在线' : '离线' }}
              </span>
            </van-cell>
            <van-cell title="设备编号" :value="currentDevice.deviceNo"/>
            <van-cell title="设备名称" :value="currentDevice.deviceName"/>
            <van-cell title="设备地点" :value="currentDevice.deviceAddress"/>
          </van-cell-group>
        </div>
      </div>
    </van-dialog>
  </div>
</template>

<script>
import {
  Search, Grid, GridItem, Icon, Switch, Stepper, Button,
  Dialog, Cell, CellGroup, RadioGroup, Radio, Empty, Toast
} from 'vant';
import {deviceCmdSend, getEquipmentListOne} from '@/api/device';

export default {
  name: 'onePage',
  components: {
    [Search.name]: Search,
    [Grid.name]: Grid,
    [GridItem.name]: GridItem,
    [Icon.name]: Icon,
    [Switch.name]: Switch,
    [Stepper.name]: Stepper,
    [Button.name]: Button,
    [Dialog.Component.name]: Dialog.Component,
    [Cell.name]: Cell,
    [CellGroup.name]: CellGroup,
    [RadioGroup.name]: RadioGroup,
    [Radio.name]: Radio,
    [Empty.name]: Empty
  },
  data() {
    return {
      loading: false,
      showBackToTop: false,
      queryParams: {
        deviceAddress: '',
        current: 1,
        pageSize: 99999999
      },
      tableData: [],
      detailDialogVisible: false,
      currentDevice: null,
      windSpeedMap: {
        0: '自动风',
        1: '低风',
        2: '中风',
        3: '高风',
        4: '固定风'
      }
    };
  },
  mounted() {
    this.initData();
  },
  computed: {
    sortedTableData() {
      return [...this.tableData].sort((a, b) => {
        // 在线设备排在前面
        if (a.isOnLine === b.isOnLine) return 0;
        return a.isOnLine ? -1 : 1;
      });
    }
  },
  methods: {
    async initData() {
      if (this.loading) return;
      this.loading = true;
      try {
        const res = await this.mockGetDeviceList(this.queryParams);
        this.tableData = res.data.records.map(item => {
          item.isOnLine = this.isDeviceOnline(item.uploadData.gmtUpdated);
          return item;
        });
      } catch (error) {
        console.error('获取设备列表失败:', error);
        this.$toast.fail('获取设备列表失败');
      } finally {
        this.loading = false;
      }
    },

    async mockGetDeviceList(params) {
      try {
        let res = await getEquipmentListOne(params);
        if (res.code === 0) {
          let list = res.data.records.map(item => {
            item.isOnLine = this.isDeviceOnline(item.uploadData.gmtUpdated);
            if (!item.uploadData.mode) {
              this.$set(item.uploadData, 'mode', 1); // 默认制冷模式
            }
            if (!item.uploadData.num) {
              this.$set(item.uploadData, 'num', 18);
            }
            return item;
          });
          return {data: {records: list}};
        }
        throw new Error(res?.msg || '获取设备列表失败');
      } catch (e) {
        console.error('获取设备列表失败:', e);
        throw e;
      }
    },

    searchQuery() {
      this.queryParams.current = 1;
      this.initData();
    },

    showDeviceDetail(row) {
      this.currentDevice = JSON.parse(JSON.stringify(row));
      if (!this.currentDevice.uploadData) {
        this.currentDevice.uploadData = {
          onoff: false,
          temp: 24,
          mode: 1, // 默认制冷模式
          wind: 0
        };
      }
      this.currentDevice.isOnLine = this.isDeviceOnline(this.currentDevice.uploadData.gmtUpdated);
      this.detailDialogVisible = true;
    },

    beforeDialogClose(action, done) {
      done();
    },

    async sendControlCommand(params) {
      if (this.loading) return;
      this.loading = true;
      try {
        const res = await deviceCmdSend(params);
        if (res && res.code === 0) {
          this.$toast.success('操作成功');
          return res;
        }
        throw new Error(res?.msg || '操作失败');
      } catch (error) {
        console.error('操作失败:', error);
        this.$toast.fail(error.message || '操作失败');
        throw error;
      } finally {
        this.loading = false;
      }
    },

    async handleTemCtrl(row, type) {
      if (!this.isDevicePowerOn(row.uploadData) || this.loading) return;

      try {
        if (type === 'temp') {
          const newMode = row.uploadData.mode === 3 ? 1 : 3; // 切换模式
          const params = {
            payload: JSON.stringify({
              mode: newMode,
              rand: Math.floor(Math.random() * 100)
            }),
            deviceNo: row.deviceNo
          };
          await this.sendControlCommand(params);
          this.$set(row.uploadData, 'mode', newMode);
        } else if (type === 'tempValue') {
          const params = {
            payload: JSON.stringify({
              temp: row.uploadData.temp,
              rand: Math.floor(Math.random() * 100)
            }),
            deviceNo: row.deviceNo
          };
          await this.sendControlCommand(params);
        }
      } catch (error) {
        console.error('温度控制失败:', error);
      }
    },

    async changeSwitch(row) {
      if (row.uploadData.onoff === null || this.loading) return;

      try {
        const newState = !this.isDevicePowerOn(row.uploadData);
        
        // 保存原始状态，用于错误时回滚
        const originalState = row.uploadData.onoff;
        
        // 模拟立即更新UI状态，提升用户体验
        this.$set(row.uploadData, 'onoff', newState);
        
        if (newState) {
          // 开机操作：分两步执行
          // 第一步：发送继电器开启命令
          const relayParams = {
            payload: JSON.stringify({
              relay: 1,
              rand: Math.floor(Math.random() * 100)
            }),
            deviceNo: row.deviceNo
          };
          await this.sendControlCommand(relayParams);
          
          // 更新继电器状态
          this.$set(row.uploadData, 'relay', true);
          
          // 第二步：发送开关状态开启命令
          const onoffParams = {
            payload: JSON.stringify({
              onoff: 1,
              rand: Math.floor(Math.random() * 100)
            }),
            deviceNo: row.deviceNo
          };
          await this.sendControlCommand(onoffParams);
        } else {
          // 关机操作：直接发送开关状态关闭命令
          const params = {
            payload: JSON.stringify({
              onoff: 0,
              rand: Math.floor(Math.random() * 100)
            }),
            deviceNo: row.deviceNo
          };
          await this.sendControlCommand(params);
        }
        
        // 更新时间戳为当前时间
        this.$set(row.uploadData, 'gmtUpdated', new Date().toISOString());
        row.isOnLine = this.isDeviceOnline(row.uploadData.gmtUpdated);
        
      } catch (error) {
        console.error('切换开关失败:', error);
        // 回滚设备状态到操作前的状态
        this.$set(row.uploadData, 'onoff', !row.uploadData.onoff);
      }
    },

    async togglePower(newState) {
      if (this.loading) return;

      try {
        // 保存原始状态，用于错误时回滚
        const originalState = this.currentDevice.uploadData.onoff;
        
        // 模拟立即更新UI状态，提升用户体验
        this.$set(this.currentDevice.uploadData, 'onoff', newState);
        
        if (newState) {
          // 开机操作：分两步执行
          // 第一步：发送继电器开启命令
          const relayParams = {
            payload: JSON.stringify({
              relay: 1,
              rand: Math.floor(Math.random() * 100)
            }),
            deviceNo: this.currentDevice.deviceNo
          };
          await this.sendControlCommand(relayParams);
          
          // 更新继电器状态
          this.$set(this.currentDevice.uploadData, 'relay', true);
          
          // 第二步：发送开关状态开启命令
          const onoffParams = {
            payload: JSON.stringify({
              onoff: 1,
              rand: Math.floor(Math.random() * 100)
            }),
            deviceNo: this.currentDevice.deviceNo
          };
          await this.sendControlCommand(onoffParams);
        } else {
          // 关机操作：直接发送开关状态关闭命令
          const params = {
            payload: JSON.stringify({
              onoff: 0,
              rand: Math.floor(Math.random() * 100)
            }),
            deviceNo: this.currentDevice.deviceNo
          };
          await this.sendControlCommand(params);
        }

        // 更新时间戳为当前时间
        const currentTime = new Date().toISOString();
        this.$set(this.currentDevice.uploadData, 'gmtUpdated', currentTime);
        this.currentDevice.isOnLine = this.isDeviceOnline(currentTime);

        const tableItem = this.tableData.find(item => item.deviceNo === this.currentDevice.deviceNo);
        if (tableItem) {
          this.$set(tableItem.uploadData, 'onoff', newState);
          this.$set(tableItem.uploadData, 'relay', newState ? true : tableItem.uploadData.relay); // 只有开机时更新relay
          this.$set(tableItem.uploadData, 'gmtUpdated', currentTime);
          tableItem.isOnLine = this.isDeviceOnline(currentTime);
        }
      } catch (error) {
        console.error('切换电源失败:', error);
        this.$set(this.currentDevice.uploadData, 'onoff', !this.currentDevice.uploadData.onoff);
      }
    },

    // 判断设备是否在线的方法：当前时间超出gmtUpdated 15分钟则视为离线
    isDeviceOnline(gmtUpdated) {
      if (!gmtUpdated) return false;

      const updatedTime = new Date(gmtUpdated);
      const currentTime = new Date();
      const diffInMinutes = (currentTime - updatedTime) / (1000 * 60);

      return diffInMinutes <= 15;
    },

    // 判断设备电源是否开启：同时考虑onoff和relay状态，任一为false则视为关闭
    isDevicePowerOn(uploadData) {
      // 如果relay为false，则直接返回false（继电器关闭表示设备关闭）
      if (uploadData.relay === false) return false;
      // 否则以onoff状态为准
      return uploadData.onoff === true;
    },

    async adjustTemperature(temp) {
      if (!this.isDevicePowerOn(this.currentDevice.uploadData) || this.loading) return;

      try {
        const params = {
          payload: JSON.stringify({
            temp: temp,
            rand: Math.floor(Math.random() * 100)
          }),
          deviceNo: this.currentDevice.deviceNo
        };
        await this.sendControlCommand(params);

        this.$set(this.currentDevice.uploadData, 'temp', temp);
        const tableItem = this.tableData.find(item => item.deviceNo === this.currentDevice.deviceNo);
        if (tableItem) {
          this.$set(tableItem.uploadData, 'temp', temp);
        }
      } catch (error) {
        console.error('调整温度失败:', error);
        this.$set(this.currentDevice.uploadData, 'temp', this.currentDevice.uploadData.temp - 1);
      }
    },

    async adjustWindSpeed(wind) {
      if (!this.currentDevice.uploadData.onoff || this.loading) return;

      try {
        const params = {
          payload: JSON.stringify({
            wind: wind,
            rand: Math.floor(Math.random() * 100)
          }),
          deviceNo: this.currentDevice.deviceNo
        };
        await this.sendControlCommand(params);

        this.$set(this.currentDevice.uploadData, 'wind', wind);
        const tableItem = this.tableData.find(item => item.deviceNo === this.currentDevice.deviceNo);
        if (tableItem) {
          this.$set(tableItem.uploadData, 'wind', wind);
        }
      } catch (error) {
        console.error('调整风速失败:', error);
        this.$set(this.currentDevice.uploadData, 'wind', this.currentDevice.uploadData.wind - 1);
      }
    }
  }
};
</script>

<style lang="scss" scoped>
.one-page-container {
  height: 100vh;
  display: flex;
  flex-direction: column;
  position: relative;

  .card-list {
    flex: 1;
    overflow-y: auto;
    padding-top: 20px;
  }
}

.air-card {
  width: 100%;
  border-radius: 0 0 12px 12px;
  background: #fff;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.08);
  overflow: hidden;
  transition: all 0.3s ease;

  &:hover {
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
    transform: translateY(-2px);
  }

  .card-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 12px 16px;
    border-bottom: 1px solid #f5f5f5;
    background-color: #fafafa;

    .device-status {
      display: flex;
      align-items: center;

      .status-dot {
        display: inline-block;
        width: 8px;
        height: 8px;
        border-radius: 50%;
        margin-right: 6px;

        &.online {
          background-color: #07c160;
          box-shadow: 0 0 6px rgba(7, 193, 96, 0.5);
        }

        &.offline {
          background-color: #ee0a24;
          box-shadow: 0 0 6px rgba(238, 10, 36, 0.5);
        }
      }

      .status-text {
        font-size: 14px;
        color: #333;
        font-weight: 500;
      }
    }

    .arrow-icon {
      color: #969799;
      font-size: 16px;
    }
  }

  .card-body {
    padding: 16px;
    position: relative;

    .offline-mask {
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      background: rgba(255, 255, 255, 0.8);
      display: flex;
      align-items: center;
      justify-content: center;
      color: #969799;
      font-size: 16px;
    }

    .device-info {
      margin-bottom: 16px;

      .device-name {
        font-size: 16px;
        font-weight: 500;
        color: #333;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        margin-bottom: 6px;
      }

      .device-location {
        font-size: 13px;
        color: #969799;
        display: flex;
        align-items: center;
      }
    }

    .device-control {
      .temp-control {
        display: flex;
        align-items: center;
        justify-content: space-between;
        margin-bottom: 12px;

        .mode-switch {
          display: flex;
          align-items: center;
          cursor: pointer;
          padding: 6px 10px;
          border-radius: 20px;
          background: #f5f5f5;
          transition: all 0.3s ease;

          .switch-icon {
            width: 28px;
            height: 28px;
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            transition: all 0.3s ease;

            .mode-img {
              width: 20px;
              height: 20px;
              object-fit: contain;
            }
          }

          .mode-text {
            margin-left: 8px;
            font-size: 14px;
            color: #333;
            min-width: 36px;
          }
        }

        .temp-stepper {
          display: flex;
          align-items: center;

          .temp-unit {
            margin-left: 8px;
            font-size: 14px;
            color: #333;
          }
        }
      }

      .power-control {
        display: flex;
        align-items: center;
        justify-content: flex-end;

        .power-switch {
          display: flex;
          align-items: center;
          cursor: pointer;
          padding: 6px 12px;
          border-radius: 20px;
          background: #f5f5f5;
          transition: all 0.3s ease;

          &:hover {
            background: #e8e8e8;
          }

          .switch-icon {
            width: 28px;
            height: 28px;
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            //background: #dcdee0;
            transition: all 0.3s ease;

            &.active {
              background: #1989fa;
            }

            .power-img {
              width: 22px;
              height: 22px;
              object-fit: contain;
            }
          }

          .power-text {
            margin-left: 8px;
            font-size: 14px;
            color: #333;
          }
        }
      }
    }
  }
}

.dialog-content {
  max-height: 60vh;
  overflow-y: auto;
  padding: 0 12px 12px;

  .control-section {
    margin-bottom: 16px;

    .van-cell-group {
      margin-bottom: 0;
    }
  }

  .detail-section {
    .detail-title {
      font-size: 15px;
      color: #969799;
      padding: 12px 0;
      font-weight: 500;
    }
  }

  .switch-container {
    display: flex;
    align-items: center;
    justify-content: flex-end;

    .power-switch, .mode-switch {
      display: flex;
      align-items: center;
      cursor: pointer;
      padding: 6px 12px;
      border-radius: 20px;
      background: #f5f5f5;
      transition: all 0.3s ease;

      &:hover {
        background: #e8e8e8;
      }

      .switch-icon {
        width: 32px;
        height: 32px;
        border-radius: 50%;
        display: flex;
        align-items: center;
        justify-content: center;
        transition: all 0.3s ease;

        &.active {
          background: #1989fa;
        }

        .power-img, .mode-img {
          width: 18px;
          height: 18px;
          object-fit: contain;
        }
      }

      .power-text, .mode-text {
        margin-left: 10px;
        font-size: 15px;
        color: #333;
      }
    }
  }

  .wind-control {
    display: flex;
    align-items: center;
    justify-content: flex-end;

    .wind-selector {
      display: flex;
      align-items: center;
      cursor: pointer;
      padding: 8px 12px;
      border-radius: 20px;
      background: #f5f5f5;
      transition: all 0.3s ease;
      width: 72px;
      justify-content: space-between;

      &:hover {
        background: #e8e8e8;
      }

      .wind-text {
        font-size: 15px;
        color: #333;
      }

      .wind-icon {
        color: #1989fa;
        font-size: 16px;
        transition: transform 0.3s ease;
      }

      &:active .wind-icon {
        transform: rotate(180deg);
      }
    }
  }

  .temp-unit {
    margin-left: 8px;
    font-size: 15px;
    color: #333;
  }

  .text-success {
    color: #07c160;
  }

  .text-danger {
    color: #ee0a24;
  }
}

// 覆盖vant默认样式
::v-deep .van-dialog {
  border-radius: 12px;
  overflow: hidden;

  .van-dialog__header {
    font-weight: 500;
    padding: 16px 0 12px;
    font-size: 17px;
  }

  .van-cell__value {
    display: flex;
    align-items: center;
  }

  .van-stepper {
    &__minus, &__plus {
      width: 24px;
      height: 24px;
    }

    input {
      height: 24px;
    }
  }
}

::v-deep .van-grid-item__content {
  padding: 0;
  border: none;
  box-shadow: none;
  background: transparent;
}
</style>
